package com.ljx.recruitment.sale.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ljx.recruitment.common.constant.CacheConstants;
import com.ljx.recruitment.common.enums.CommonStatusTypeEnum;
import com.ljx.recruitment.common.exception.ApiException;
import com.ljx.recruitment.common.util.RedisUtil;
import com.ljx.recruitment.sale.domain.entity.AccessToken;
import com.ljx.recruitment.sale.domain.vo.req.AccessTokenSubmitReq;
import com.ljx.recruitment.sale.enums.AccessTokenTypeEnum;
import com.ljx.recruitment.sale.mapper.AccessTokenMapper;
import com.ljx.recruitment.sale.service.AccessTokenService;
import com.ljx.recruitment.sale.service.AccessTokenStrategy;
import com.ljx.recruitment.sale.service.impl.token.TrialApplicationAccessTokenStrategy;
import com.ljx.recruitment.security.util.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;

@Service
public class AccessTokenServiceImpl extends ServiceImpl<AccessTokenMapper, AccessToken> implements AccessTokenService {

    @Autowired
    private AccessTokenMapper accessTokenMapper;

    @Value("${recruitment.url.backend}")
    private String backendUrl;

    @Override
    public String submit(AccessTokenSubmitReq req) {
        String token = RandomUtil.randomString(20);
        String url = createAccessTokenUrl(backendUrl, token);
        AccessToken accessToken = new AccessToken(req.getTokenType(), req.getTokenParams(), token, UserUtil.getUserId(), url);
        accessTokenMapper.insert(accessToken);
        RedisUtil.set(CacheConstants.getKey(CacheConstants.ACCESS_TOKEN, token), UserUtil.getUserId(), CacheConstants.ACCESS_TOKEN_EXPIRE_TIME);
        return url;
    }

    private String createAccessTokenUrl(String backendUrl, String token) {
        return UriComponentsBuilder.fromHttpUrl(backendUrl + "/api/access_token/parse/" + token)
                .toUriString();
    }

    private AccessTokenStrategy getAccessTokenStrategy(Integer tokenType) {
        if (tokenType.equals(AccessTokenTypeEnum.TRIAL_APPLICATION.getKey())) {
            return SpringUtil.getBean(TrialApplicationAccessTokenStrategy.class);
        } else {
            throw new ApiException("无效类型");
        }
    }

    @Override
    public String parseToken(String token) {
        String userId = RedisUtil.get(CacheConstants.getKey(CacheConstants.ACCESS_TOKEN, token));
        if (StrUtil.isEmpty(userId)) {
            throw new ApiException("链接已过期");
        }
        AccessToken accessToken = getByToken(token);
        AccessTokenStrategy accessTokenStrategy = getAccessTokenStrategy(accessToken.getTokenType());
        return accessTokenStrategy.parseToken(accessToken);
    }

    @Override
    public AccessToken getByToken(String token) {
        if (StrUtil.isEmpty(token)) {
            throw new ApiException("token不能为空");
        }
        return accessTokenMapper.selectOne(new LambdaQueryWrapper<AccessToken>()
                .eq(AccessToken::getToken, token)
                .eq(AccessToken::getStatus, CommonStatusTypeEnum.NORMAL.getKey()));
    }

}
